// 《围棋》作者版权所有。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package fs

import (
	"errors"
	"sort"
)

// ReadDirFS是由文件系统
// 实现的接口，它提供了ReadDir的优化实现。
type ReadDirFS interface {
	FS

	// ReadDir读取命名目录
	// 并返回按文件名排序的目录项列表。
	ReadDir(name string) ([]DirEntry, error)
}

// ReadDir读取命名目录
// 并返回按文件名排序的目录项列表。
// 
// 如果fs实现ReadDirFS，ReadDir将调用fs.ReadDir。
// 否则ReadDir调用fs.Open并对返回的文件使用ReadDir和Close 
// 。
func ReadDir(fsys FS, name string) ([]DirEntry, error) {
	if fsys, ok := fsys.(ReadDirFS); ok {
		return fsys.ReadDir(name)
	}

	file, err := fsys.Open(name)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	dir, ok := file.(ReadDirFile)
	if !ok {
		return nil, &PathError{Op: "readdir", Path: name, Err: errors.New("not implemented")}
	}

	list, err := dir.ReadDir(-1)
	sort.Slice(list, func(i, j int) bool { return list[i].Name() < list[j].Name() })
	return list, err
}

// dirInfo是基于FileInfo的DirEntry。
type dirInfo struct {
	fileInfo FileInfo
}

func (di dirInfo) IsDir() bool {
	return di.fileInfo.IsDir()
}

func (di dirInfo) Type() FileMode {
	return di.fileInfo.Mode().Type()
}

func (di dirInfo) Info() (FileInfo, error) {
	return di.fileInfo, nil
}

func (di dirInfo) Name() string {
	return di.fileInfo.Name()
}

// FileInfoToDirEntry返回从info返回信息的DirEntry。
// 如果info为nil，则FileInfoToDirEntry返回nil。
func FileInfoToDirEntry(info FileInfo) DirEntry {
	if info == nil {
		return nil
	}
	return dirInfo{fileInfo: info}
}
